#include "input.h"
#include "log.h"
#include "sdl\sdl.h"

////////////////////////////////////////////////////////////////////////////////

struct KeyConv
{
  Key key;
  SDLKey sdl_key;
};

static KeyConv key_conv_lut[] =
{
  {KEY_BACKSPACE, SDLK_BACKSPACE},
  {KEY_TAB, SDLK_TAB},
  {KEY_RETURN, SDLK_RETURN},
  {KEY_PAUSE, SDLK_PAUSE},
  {KEY_ESCAPE, SDLK_ESCAPE},
  {KEY_SPACE, SDLK_SPACE},
  {KEY_EXCLAIM, SDLK_EXCLAIM},
  {KEY_DBLQUOTE, SDLK_QUOTEDBL},
  {KEY_HASH, SDLK_HASH},
  {KEY_DOLLAR, SDLK_DOLLAR},
  {KEY_AMPERSAND, SDLK_AMPERSAND},
  {KEY_QUOTE, SDLK_QUOTE},
  {KEY_LEFTPAREN, SDLK_LEFTPAREN},
  {KEY_RIGHTPAREN, SDLK_RIGHTPAREN},
  {KEY_ASTERISK, SDLK_ASTERISK},
  {KEY_PLUS, SDLK_PLUS},
  {KEY_COMMA, SDLK_COMMA},
  {KEY_MINUS, SDLK_MINUS},
  {KEY_PERIOD, SDLK_PERIOD},
  {KEY_SLASH, SDLK_SLASH},
  {KEY_0, SDLK_0},
  {KEY_1, SDLK_1},
  {KEY_2, SDLK_2},
  {KEY_3, SDLK_3},
  {KEY_4, SDLK_4},
  {KEY_5, SDLK_5},
  {KEY_6, SDLK_6},
  {KEY_7, SDLK_7},
  {KEY_8, SDLK_8},
  {KEY_9, SDLK_9},
  {KEY_COLON, SDLK_COLON},
  {KEY_SEMICOLON, SDLK_SEMICOLON},
  {KEY_LESS, SDLK_LESS},
  {KEY_EQUALS, SDLK_EQUALS},
  {KEY_GREATER, SDLK_GREATER},
  {KEY_QUESTION, SDLK_QUESTION},
  {KEY_AT, SDLK_AT},
  {KEY_LEFTBRACKET, SDLK_LEFTBRACKET},
  {KEY_BACKSLASH, SDLK_BACKSLASH},
  {KEY_RIGHTBRACKET, SDLK_RIGHTBRACKET},
  {KEY_CARET, SDLK_CARET},
  {KEY_UNDERSCORE, SDLK_UNDERSCORE},
  {KEY_BACKQUOTE, SDLK_BACKQUOTE},
  {KEY_A, SDLK_a},
  {KEY_B, SDLK_b},
  {KEY_C, SDLK_c},
  {KEY_D, SDLK_d},
  {KEY_E, SDLK_e},
  {KEY_F, SDLK_f},
  {KEY_G, SDLK_g},
  {KEY_H, SDLK_h},
  {KEY_I, SDLK_i},
  {KEY_J, SDLK_j},
  {KEY_K, SDLK_k},
  {KEY_L, SDLK_l},
  {KEY_M, SDLK_m},
  {KEY_N, SDLK_n},
  {KEY_O, SDLK_o},
  {KEY_P, SDLK_p},
  {KEY_Q, SDLK_q},
  {KEY_R, SDLK_r},
  {KEY_S, SDLK_s},
  {KEY_T, SDLK_t},
  {KEY_U, SDLK_u},
  {KEY_V, SDLK_v},
  {KEY_W, SDLK_w},
  {KEY_X, SDLK_x},
  {KEY_Y, SDLK_y},
  {KEY_Z, SDLK_z},
  {KEY_DELETE, SDLK_DELETE},
};

////////////////////////////////////////////////////////////////////////////////

Key Input_convKey(SDLKey sdl_key)
{
  unsigned length = sizeof(key_conv_lut) / sizeof(key_conv_lut[0]);
  
  for (unsigned i = 0; i < length; i++)
  {
    if (key_conv_lut[i].sdl_key == sdl_key)
    {
      return key_conv_lut[i].key;
    }
  }
  
  return KEY_NONE;
}

static bool Input_mousePress(Event* event, const SDL_Event& sdl_event)
{
  event->type = EVENT_MOUSE_PRESS;
  
  if (sdl_event.button.button == SDL_BUTTON_LEFT)
  {
    event->mouse_press.button = MOUSE_BUTTON_LEFT;
  }
  else
  {
    event->mouse_press.button = MOUSE_BUTTON_RIGHT;
  }
  
  event->mouse_press.pos.x = sdl_event.button.x;
  event->mouse_press.pos.y = sdl_event.button.y;
  
  return true;
}

static bool Input_mouseRelease(Event* event, const SDL_Event& sdl_event)
{
  event->type = EVENT_MOUSE_RELEASE;
  
  if (sdl_event.button.button == SDL_BUTTON_LEFT)
  {
    event->mouse_press.button = MOUSE_BUTTON_LEFT;
  }
  else
  {
    event->mouse_press.button = MOUSE_BUTTON_RIGHT;
  }
  
  event->mouse_press.pos.x = sdl_event.button.x;
  event->mouse_press.pos.y = sdl_event.button.y;
  
  return true;
}

static bool Input_keyPress(Event* event, const SDL_Event& sdl_event)
{
  event->type = EVENT_KEY_DOWN;
  event->key_press.key = Input_convKey(sdl_event.key.keysym.sym);
  event->key_press.c = sdl_event.key.keysym.unicode;
  
  return event->key_press.key != KEY_NONE;
}

////////////////////////////////////////////////////////////////////////////////

void Input_init()
{
  SDL_EnableUNICODE(true);
}

bool Input_pollEvent(Event* event)
{
  SDL_Event sdl_event;
  bool found_event = false;
  
  while (!found_event && SDL_PollEvent(&sdl_event))
  {
    switch (sdl_event.type)
    {
      case SDL_QUIT:
        event->type = EVENT_QUIT;
        found_event = true;
        break;
        
        case SDL_MOUSEBUTTONDOWN:
          found_event = Input_mousePress(event, sdl_event);
          break;
          
        case SDL_MOUSEBUTTONUP:
          found_event = Input_mouseRelease(event, sdl_event);
          break;
          
        case SDL_KEYDOWN:
          found_event = Input_keyPress(event, sdl_event);
          break;
          
        default:
          break;
    }
  }
  
  return found_event;
}
